﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using BrainTechLLC;
using BrainTechLLC.ThreadSafeObjects;

namespace BrainTechLLC.Silverlight.ClientApplication.Controls
{
    public partial class Map : UserControl
    {
        public int ShowX = 10;
        public int ShowY = 10;
        public CharImage charImage;

        public MapSquare[,] MapSquares;

        public static readonly DependencyProperty UpperLeftLocationProperty = DependencyProperty.Register(
            "UpperLeftLocation",
            typeof(LocationInt),
            typeof(Map),
            new PropertyMetadata(new LocationInt(1, 1, 1), new PropertyChangedCallback(UpperLeftLocationChanged)));

        public LocationInt UpperLeftLocation
        {
            get { return (LocationInt)GetValue(UpperLeftLocationProperty); }
            set { SetValue(UpperLeftLocationProperty, value); }
        }

        private static void UpperLeftLocationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Map t = (Map)d;
            t.UpperLeftLocation = e.NewValue as LocationInt;
            t.Dispatcher.BeginInvoke(() => t.UpdateMap());
        }

        public static readonly DependencyProperty WorldMapProperty = DependencyProperty.Register(
            "WorldMap",
            typeof(SparseArrayCustom<GameLocation>),
            typeof(Map),
            new PropertyMetadata(null, new PropertyChangedCallback(WorldMapChanged)));

        public SparseArrayCustom<GameLocation> WorldMap
        {
            get { return (SparseArrayCustom<GameLocation>)GetValue(WorldMapProperty); }
            set { SetValue(WorldMapProperty, value); }
        }

        private static void WorldMapChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Map t = (Map)d;
            t.WorldMap = e.NewValue as SparseArrayCustom<GameLocation>;
            t.Dispatcher.BeginInvoke(() => t.UpdateMap());
        }

        public void UpdateMap()
        {
            SparseArrayCustom<GameLocation> map = WorldMap;

            if (map == null)
                return;

            for (int n = grid.Children.Count - 1; n >= 0; n--)
            {
                if (grid.Children[n] is MapSquare)
                    grid.Children.RemoveAt(n);
            }

            int xStart = UpperLeftLocation.X;
            int yStart = UpperLeftLocation.Y;
            int zStart = UpperLeftLocation.Z;

            MapSquares = new MapSquare[ShowX, ShowY];

            for (int x = 0; x < ShowX; x++)
            {
                for (int y = 0; y < ShowY; y++)
                {
                    int actualX = xStart + x;
                    int actualY = yStart + y;
                    int actualZ = zStart;
                    GameLocation loc = map[actualX, actualY, actualZ];

                    if (loc != null)
                    {
                        MapSquare sq = new MapSquare()
                        {
                            Location = loc,
                            GraphicUri = new Uri("/FloppyDriveSearch.png", UriKind.Relative)
                        };
                        MapSquares[x, y] = sq;
                        sq.SetValue(Grid.ColumnProperty, x);
                        sq.SetValue(Grid.RowProperty, y);
                        grid.Children.Add(sq);
                    }
                }
            }
            UpdateLocation(DataAccess.CurrentlyPlaying.AssociatedID, DataAccess.CurrentlyPlaying.LocationInt);
        }

        public void UpdateLocation(long id, LocationInt loc)
        {
            if (DataAccess.CurrentlyPlaying == null)
                return;

            int xStart = UpperLeftLocation.X;
            int yStart = UpperLeftLocation.Y;
            int zStart = UpperLeftLocation.Z;

            if (id == DataAccess.CurrentlyPlaying.AssociatedID)
            {
                if (loc != DataAccess.CurrentlyPlaying.LocationInt)
                {
                    Console.Write("Blah");
                }

                grid.Children.Remove(charImage);

                charImage.SetValue(Grid.ColumnProperty, DataAccess.CurrentlyPlaying.LocationInt.X - xStart);
                charImage.SetValue(Grid.RowProperty, DataAccess.CurrentlyPlaying.LocationInt.Y - yStart);

                grid.Children.Add(charImage);
            }
        }

        public Map()
        {
            // Required to initialize variables
            InitializeComponent();

            MapSquares = new MapSquare[ShowX, ShowY];
            charImage = new CharImage();

            for (int x = 0; x < ShowX; x++)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(32, GridUnitType.Pixel) });
            }
            grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });

            for (int y = 0; y < 10; y++)
            {
                grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(32, GridUnitType.Pixel) });
            }
            grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });

            DataAccess.ThingMoved += new EventHandler<ObjectEventArgsNonRef<long, LocationInt, long>>(DataAccess_ThingMoved);
        }

        void DataAccess_ThingMoved(object sender, ObjectEventArgsNonRef<long, LocationInt, long> e)
        {
            Dispatcher.BeginInvoke(() => UpdateLocation(e.obj1, e.obj2));
        }
    }
}